package com.haredot.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.http.HttpMethod;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Part;
import java.util.ArrayList;
import java.util.List;

/**
 * 日志配置类
 */
@ConfigurationProperties(prefix = "sys.log")
public class LogProperties {
    /**
     * 业务日志
     */
    private ServiceLog serviceLog = new ServiceLog();

    /**
     * 日志类型
     */
    public static enum LogType {
        ALL , ERROR
    }

    /**
     * 业务日志
     */
    public static class ServiceLog {
        /**
         * 是否启用
         */
        private boolean enable  = true ;
        /**
         * 记录的请求方式, 默认记录 GET, POST, PUT , DELETE, PATCH
         */
        private List<HttpMethod> methods = new ArrayList<>(List.of(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.PATCH, HttpMethod.DELETE));

        /**
         * 是否记录 访问结果, 默认不记录
         */
        private boolean result = false ;
        /**
         * 添加排除的请求方式
         */
        private List<HttpMethod> addExcludeMethods ;
        /**
         * 添加排序的方法参数类型
         */
        private List<Class<?>> addExcludeRecordArgList ;
        /**
         * 添加允许记录的请求方式
         */
        private List<HttpMethod> addMethods ;

        /**
         * 日志类型，默认记录全部日志，
         */
        private LogType logType = LogType.ALL;
        /**
         * 不需要记录的方法参数列表，
         * 默认 不记录 Part, MultipartFile,
         * request, response, session, servletContet,
         * bindResult
         */
        private List<Class<?>> excludeRecordArgList =
                new ArrayList<>(List.of(Part.class,
                        MultipartFile.class,
                        HttpServletRequest.class,
                        HttpServletResponse.class,
                        HttpSession.class,
                        ServletContext.class,
                        BindingResult.class)) ;

        public boolean isEnable() {
            return enable;
        }

        public void setEnable(boolean enable) {
            this.enable = enable;
        }

        public List<HttpMethod> getMethods() {
            return methods;
        }

        public void setMethods(List<HttpMethod> methods) {
            this.methods = methods;
        }

        public boolean isResult() {
            return result;
        }

        public void setResult(boolean result) {
            this.result = result;
        }

        public List<Class<?>> getExcludeRecordArgList() {
            return excludeRecordArgList;
        }

        public List<HttpMethod> getAddExcludeMethods() {
            return addExcludeMethods;
        }

        public List<Class<?>> getAddExcludeRecordArgList() {
            return addExcludeRecordArgList;
        }

        public void setAddExcludeRecordArgList(List<Class<?>> addExcludeRecordArgList) {
            this.addExcludeRecordArgList = addExcludeRecordArgList;
            this.excludeRecordArgList.addAll(addExcludeRecordArgList) ;
        }

        public void setExcludeRecordArgList(List<Class<?>> excludeRecordArgList) {
            this.excludeRecordArgList = excludeRecordArgList;
        }

        /**
         * 排除某个拦截的方法
         */
        public void setAddExcludeMethods(List<HttpMethod> addExcludeMethods) {
            this.addExcludeMethods = addExcludeMethods;
            this.methods.removeIf(method ->  addExcludeMethods.contains(method)) ;
        }

        public List<HttpMethod> getAddMethods() {
            return addMethods;
        }

        public void setAddMethods(List<HttpMethod> addMethods) {
            this.addMethods = addMethods;
            this.methods.addAll(addMethods) ;
        }

        public LogType getLogType() {
            return logType;
        }

        public void setLogType(LogType logType) {
            this.logType = logType;
        }
    }

    public ServiceLog getServiceLog() {
        return serviceLog;
    }

    public void setServiceLog(ServiceLog serviceLog) {
        this.serviceLog = serviceLog;
    }
}
